home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / bash-1.12 / dist / print_cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-30  |  13.0 KB  |  587 lines

  1. /* print_command -- A way to make readable commands from a command tree. */
  2. /* Copyright (C) 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Bash, the Bourne Again SHell.
  5.  
  6. Bash is free software; you can redistribute it and/or modify it under
  7. the terms of the GNU General Public License as published by the Free
  8. Software Foundation; either version 1, or (at your option) any later
  9. version.
  10.  
  11. Bash is distributed in the hope that it will be useful, but WITHOUT ANY
  12. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14. for more details.
  15.  
  16. You should have received a copy of the GNU General Public License along
  17. with Bash; see the file COPYING.  If not, write to the Free Software
  18. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  19.  
  20. #include <stdio.h>
  21.  
  22. #if defined (HAVE_VFPRINTF)
  23. #include <varargs.h>
  24. #endif
  25.  
  26. #include "shell.h"
  27. #include "y.tab.h"
  28.  
  29. static int indentation = 0;
  30. static int indentation_amount = 4;
  31.  
  32. #define PRINTED_COMMAND_GROW_SIZE 1024
  33. char *the_printed_command = (char *)NULL;
  34. int the_printed_command_size = 0;
  35. int command_string_index = 0;
  36.  
  37. /* Non-zero means the stuff being printed is inside of a function def. */
  38. static int inside_function_def = 0;
  39. static int skip_this_indent = 0;
  40.  
  41. /* Print COMMAND (a command tree) on standard output. */
  42. print_command (command)
  43.      COMMAND *command;
  44. {
  45.   char *make_command_string ();
  46.   command_string_index = 0;
  47.   printf ("%s", make_command_string (command));
  48. }
  49.  
  50. /* Make a string which is the printed representation of the command
  51.    tree in COMMAND.  We return this string.  However, the string is
  52.    not consed, so you have to do that yourself if you want it to
  53.    remain around. */
  54. char *
  55. make_command_string (command)
  56.      COMMAND *command;
  57. {
  58.   command_string_index = 0;
  59.   make_command_string_internal (command);
  60.   return (the_printed_command);
  61. }
  62.  
  63. /* The internal function.  This is the real workhorse. */
  64. make_command_string_internal (command)
  65.      COMMAND *command;
  66. {
  67.   if (!command)
  68.     {
  69.       cprintf ("");
  70.     }
  71.   else
  72.     {
  73.       if (skip_this_indent)
  74.     skip_this_indent--;
  75.       else
  76.     indent (indentation);
  77.  
  78.       if (command->flags & CMD_WANT_SUBSHELL)
  79.     cprintf ("( ");
  80.  
  81.       if (command->flags & CMD_INVERT_RETURN)
  82.     cprintf (" ! ");
  83.  
  84.       switch (command->type)
  85.     {
  86.     case cm_for:
  87.       print_for_command (command->value.For);
  88.       break;
  89.  
  90.     case cm_case:
  91.       print_case_command (command->value.Case);
  92.       break;
  93.  
  94.     case cm_while:
  95.       print_while_command (command->value.While);
  96.       break;
  97.  
  98.     case cm_until:
  99.       print_until_command (command->value.While);
  100.       break;
  101.  
  102.     case cm_if:
  103.       print_if_command (command->value.If);
  104.       break;
  105.  
  106.     case cm_simple:
  107.       print_simple_command (command->value.Simple);
  108.       break;
  109.  
  110.     case cm_connection: 
  111.  
  112.       skip_this_indent++;
  113.       make_command_string_internal (command->value.Connection->first);
  114.  
  115.       switch (command->value.Connection->connector)
  116.         {
  117.         case '&':
  118.         case '|':
  119.           {
  120.         char c = command->value.Connection->connector;
  121.         cprintf (" %c", c);
  122.         if (c != '&' || command->value.Connection->second)
  123.           {
  124.             cprintf (" ");
  125.             skip_this_indent++;
  126.           }
  127.           }
  128.           break;
  129.  
  130.         case AND_AND:
  131.           cprintf (" && ");
  132.           if (command->value.Connection->second)
  133.         skip_this_indent++;
  134.           break;
  135.  
  136.         case OR_OR:
  137.           cprintf (" || ");
  138.           if (command->value.Connection->second)
  139.         skip_this_indent++;
  140.           break;
  141.     
  142.         case ';':
  143.           cprintf (";");
  144.  
  145.           if (inside_function_def)
  146.         cprintf ("\n");
  147.           else
  148.         {
  149.           cprintf (" ");
  150.           if (command->value.Connection->second)
  151.             skip_this_indent++;
  152.         }
  153.           break;
  154.  
  155.         default:
  156.           cprintf ("OOPS!  Bad connector `%d'!",
  157.                command->value.Connection->connector);
  158.           break;
  159.         }
  160.  
  161.       make_command_string_internal (command->value.Connection->second);
  162.       break;
  163.       
  164.     case cm_function_def:
  165.       print_function_def (command->value.Function_def);
  166.       break;
  167.  
  168.     case cm_group:
  169.       print_group_command (command->value.Group);
  170.       break;
  171.  
  172.     default:
  173.       programming_error ("OOPS!  Bad command type `%d'!", command->type);
  174.       break;
  175.     }
  176.  
  177.       if (command->flags & CMD_WANT_SUBSHELL)
  178.     cprintf (" )");
  179.  
  180.       if (command->redirects)
  181.     print_redirection_list (command->redirects);
  182.     }
  183. }
  184.  
  185. print_word_list (list, separator)
  186.      WORD_LIST *list;
  187.      char *separator;
  188. {
  189.   while (list)
  190.     {
  191.       printf ("%s", list->word->word);
  192.       list = list->next;
  193.       if (list)
  194.     printf ("%s", separator);
  195.     }
  196. }
  197.  
  198. command_print_word_list (list, separator)
  199.      WORD_LIST *list;
  200.      char *separator;
  201. {
  202.   while (list)
  203.     {
  204.       cprintf ("%s", list->word->word);
  205.       list = list->next;
  206.       if (list)
  207.     cprintf ("%s", separator);
  208.     }
  209. }
  210.  
  211. print_for_command (for_command)
  212.      FOR_COM *for_command;
  213. {
  214.   cprintf ("for %s in ", for_command->name->word);
  215.   command_print_word_list (for_command->map_list, " ");
  216.   cprintf (";");
  217.   newline ("do\n");
  218.   indentation += indentation_amount;
  219.   make_command_string_internal (for_command->action);
  220.   cprintf (";");
  221.   indentation -= indentation_amount;
  222.   newline ("done");
  223. }
  224.  
  225. print_group_command (group_command)
  226.      GROUP_COM *group_command;
  227. {
  228.   cprintf ("{ ");
  229.  
  230.   if (!inside_function_def)
  231.     skip_this_indent++;
  232.   else
  233.     cprintf ("\n");
  234.  
  235.   make_command_string_internal (group_command->command);
  236.  
  237.   if (inside_function_def)
  238. #if 0
  239.     cprintf ("; \n}");
  240. #else
  241.     cprintf ("\n}");
  242. #endif
  243.   else
  244.     cprintf (" }");
  245. }
  246.  
  247. print_case_command (case_command)
  248.      CASE_COM *case_command;
  249. {
  250.   cprintf ("case %s in ", case_command->word->word);
  251.   if (case_command->clauses)
  252.     print_case_clauses (case_command->clauses);
  253.   newline ("esac");
  254. }
  255.  
  256. print_case_clauses (clauses)
  257.      PATTERN_LIST *clauses;
  258. {
  259.   indentation += indentation_amount;
  260.   while (clauses)
  261.     {
  262.       newline ("");
  263.       command_print_word_list (clauses->patterns, " | ");
  264.       cprintf (")\n");
  265.       indentation += indentation_amount;
  266.       make_command_string_internal (clauses->action);
  267.       indentation -= indentation_amount;
  268.       newline (";;");
  269.       clauses = clauses->next;
  270.     }
  271.   indentation -= indentation_amount;
  272. }
  273.  
  274. print_while_command (while_command)
  275.      WHILE_COM *while_command;
  276. {
  277.   print_until_or_while (while_command, "while");
  278. }
  279.  
  280. print_until_command (while_command)
  281.      WHILE_COM *while_command;
  282. {
  283.   print_until_or_while (while_command, "until");
  284. }
  285.  
  286. print_until_or_while (while_command, which)
  287.      WHILE_COM *while_command;
  288.      char *which;
  289. {
  290.   cprintf ("%s ", which);
  291.   skip_this_indent++;
  292.   make_command_string_internal (while_command->test);
  293.   cprintf (";");
  294.   newline ("do\n");
  295.   indentation += indentation_amount;
  296.   make_command_string_internal (while_command->action);
  297.   indentation -= indentation_amount;
  298.   cprintf (";");
  299.   newline ("done");
  300. }
  301.  
  302. print_if_command (if_command)
  303.      IF_COM *if_command;
  304. {
  305.   cprintf ("if ");
  306.   skip_this_indent++;
  307.   make_command_string_internal (if_command->test);
  308.   cprintf (" ; then\n");
  309.   indentation += indentation_amount;
  310.   make_command_string_internal (if_command->true_case);
  311.   indentation -= indentation_amount;
  312.  
  313.   if (if_command->false_case)
  314.     {
  315.       cprintf (";");
  316.       newline ("else\n");
  317.       indentation += indentation_amount;
  318.       make_command_string_internal (if_command->false_case);
  319.       indentation -= indentation_amount;
  320.     }
  321.   cprintf (" ;");
  322.   newline ("fi");
  323. }
  324.  
  325. print_simple_command (simple_command)
  326.      SIMPLE_COM *simple_command;
  327. {
  328.   command_print_word_list (simple_command->words, " ");
  329.  
  330.   if (simple_command->redirects)
  331.     {
  332.       cprintf (" ");
  333.       print_redirection_list (simple_command->redirects);
  334.     }
  335. }
  336.  
  337. print_redirection_list (redirects)
  338.      REDIRECT *redirects;
  339. {
  340.   while (redirects)
  341.     {
  342.       print_redirection (redirects);
  343.       cprintf (" ");
  344.       redirects = redirects->next;
  345.     }
  346. }
  347.  
  348. print_redirection (redirect)
  349.      REDIRECT *redirect;
  350. {
  351.   int kill_leading = 0;
  352.   int redirector = redirect->redirector;
  353.   WORD_DESC *redirectee = redirect->redirectee.filename;
  354.  
  355.   switch (redirect->instruction)
  356.     {
  357.     case r_output_direction:
  358.       if (redirector != 1)
  359.     cprintf ("%d", redirector);
  360.       cprintf (">%s", redirectee->word);
  361.       break;
  362.  
  363.     case r_input_direction:
  364.       if (redirector != 0)
  365.     cprintf ("%d", redirector);
  366.       cprintf ("<%s", redirectee->word);
  367.       break;
  368.  
  369.     case r_inputa_direction:    /* Redirection created by the sh. */
  370.       cprintf ("&");
  371.       break;
  372.  
  373.     case r_appending_to:
  374.       if (redirector != 1)
  375.     cprintf ("%d", redirector);
  376.       cprintf (">>%s", redirectee->word);
  377.       break;
  378.  
  379.     case r_deblank_reading_until:
  380.       kill_leading++;
  381.       /* ... */
  382.     case r_reading_until:
  383.       if (redirector != 0)
  384.     cprintf ("%d", redirector);
  385.       cprintf ("<<%s%s", kill_leading? "-" : "", redirect->here_doc_eof);
  386.       /* This is only important if we are printing a function definition
  387.      for export.  If not, we could overrun the buffer that `cprintf'
  388.      writes into, quite unexpectedly -- when unpacking shar files, for
  389.      instance. */
  390.       if (inside_function_def)
  391.     {
  392.       cprintf ("\n");
  393.       cprintf ("%s%s", redirect->redirectee.filename->word,
  394.                redirect->here_doc_eof);
  395.     }
  396.       break;
  397.  
  398.     case r_duplicating_input:
  399.       cprintf ("%d<&%d", redirector, (int)redirectee);
  400.       break;
  401.  
  402.     case r_duplicating_output:
  403.       cprintf ("%d>&%d", redirector, (int)redirectee);
  404.       break;
  405.  
  406.     case r_duplicating_input_word:
  407.       cprintf ("%d<&%s", redirector, redirectee->word);
  408.       break;
  409.  
  410.     case r_duplicating_output_word:
  411.       cprintf ("%d>&%s", redirector, redirectee->word);
  412.       break;
  413.  
  414.     case r_close_this:
  415.       cprintf ("%d>&-", redirector);
  416.       break;
  417.  
  418.     case r_err_and_out:
  419.       cprintf (">&%s", redirectee->word);
  420.       break;
  421.  
  422.     case r_input_output:
  423.       if (redirector != 1)
  424.     cprintf ("%d", redirector);
  425.       cprintf ("<>%s", redirectee->word);
  426.       break;
  427.  
  428.     case r_output_force:
  429.       if (redirector != 1)
  430.     cprintf ("%d", redirector);
  431.       cprintf (">|%s", redirectee->word);
  432.       break;
  433.     }
  434. }
  435.  
  436. static void
  437. reset_locals ()
  438. {
  439.   inside_function_def = 0;
  440.   indentation = 0;
  441. }
  442.  
  443. print_function_def (func)
  444.      FUNCTION_DEF *func;
  445. {
  446.   cprintf ("function %s () \n", func->name->word);
  447.   add_unwind_protect (reset_locals, 0);
  448.   inside_function_def++;
  449.   skip_this_indent++;
  450.   indentation += indentation_amount;
  451.   make_command_string_internal (func->command);
  452.   remove_unwind_protect ();
  453.   indentation -= indentation_amount;
  454.   inside_function_def--;
  455. }
  456.  
  457. /* Return the string representation of the named function.
  458.    NAME is the name of the function.
  459.    COMMAND is the function body.  It should be a GROUP_COM.
  460.    MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
  461.   */
  462. char *
  463. named_function_string (name, command, multi_line)
  464.      char *name;
  465.      COMMAND *command;
  466.      int multi_line;
  467. {
  468.   char *result;
  469.   int old_indent = indentation, old_amount = indentation_amount;
  470.  
  471.   command_string_index = 0;
  472.  
  473.   if (name && *name)
  474.     cprintf ("%s ", name);
  475.  
  476.   cprintf ("() ");
  477.  
  478.   if (!multi_line)
  479.     {
  480.       indentation = 1;
  481.       indentation_amount = 0;
  482.     }
  483.   else
  484.     {
  485.       cprintf ("\n");
  486.       indentation += indentation_amount;
  487.     }
  488.  
  489.   inside_function_def++;
  490.   skip_this_indent++;
  491.   make_command_string_internal (command);
  492.  
  493.   indentation = old_indent;
  494.   indentation_amount = old_amount;
  495.   inside_function_def--;
  496.  
  497.   result = the_printed_command;
  498.  
  499.   if (!multi_line)
  500.     {
  501. #if 0
  502.       register int i;
  503.       for (i = 0; result[i]; i++)
  504.     if (result[i] == '\n')
  505.       {
  506.         strcpy (&result[i], &result[i + 1]);
  507.         --i;
  508.       }
  509. #else
  510.       if (result[2] == '\n')    /* XXX -- experimental */
  511.         strcpy (&result[2], &result[3]);
  512. #endif
  513.     }
  514.  
  515.   return (result);
  516. }
  517.  
  518. newline (string)
  519.      char *string;
  520. {
  521.   cprintf ("\n");
  522.   indent (indentation);
  523.   cprintf ("%s", string);
  524. }
  525.  
  526. indent (amount)
  527.      int amount;
  528. {
  529.   while (amount-- > 0)
  530.     cprintf (" ");
  531. }
  532.  
  533. #if !defined (HAVE_VFPRINTF)
  534. /* How to make the string. */
  535. cprintf (control, arg1, arg2, arg3, arg4, arg5)
  536.      char *control;
  537. {
  538.   char temp_buffer[5000];
  539.   int l;
  540.  
  541.   sprintf (temp_buffer, control, arg1, arg2, arg3, arg4, arg5);
  542.   l = strlen (temp_buffer);
  543.  
  544.   if (!the_printed_command)
  545.     the_printed_command =
  546.       (char *)xmalloc (the_printed_command_size = PRINTED_COMMAND_GROW_SIZE);
  547.  
  548.   while (the_printed_command_size <= command_string_index + l)
  549.     the_printed_command = (char *)
  550.       xrealloc (the_printed_command,
  551.         the_printed_command_size += PRINTED_COMMAND_GROW_SIZE);
  552.  
  553.   strcpy (the_printed_command + command_string_index, temp_buffer);
  554.   command_string_index += l;
  555. }
  556.  
  557. #else /* We have support for varargs. */
  558.  
  559. /* How to make the string. */
  560. cprintf (va_alist)
  561.      va_dcl
  562. {
  563.   char temp_buffer[5000];
  564.   int l;
  565.   char *control;
  566.   va_list args;
  567.  
  568.   va_start (args);
  569.   control = va_arg (args, char *);
  570.   vsprintf (temp_buffer, control, args);
  571.   va_end (args);
  572.   l = strlen (temp_buffer);
  573.  
  574.   if (!the_printed_command)
  575.     the_printed_command =
  576.       (char *)xmalloc (the_printed_command_size = PRINTED_COMMAND_GROW_SIZE);
  577.  
  578.   while (the_printed_command_size <= command_string_index + l)
  579.     the_printed_command = (char *)
  580.       xrealloc (the_printed_command,
  581.         the_printed_command_size += PRINTED_COMMAND_GROW_SIZE);
  582.  
  583.   strcpy (the_printed_command + command_string_index, temp_buffer);
  584.   command_string_index += l;
  585. }
  586. #endif /* HAVE_VFPRINTF */
  587.